package ch.fusun.baron.printing.ui;

import java.util.LinkedList;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;

import ch.fusun.baron.client.rmi.ClientService;
import ch.fusun.baron.core.injection.Inject;
import ch.fusun.baron.core.injection.ReInjector;
import ch.fusun.baron.core.service.UserService;
import ch.fusun.baron.data.DataListener;
import ch.fusun.baron.data.DataUpdate;
import ch.fusun.baron.printing.MessagingService;
import ch.fusun.baron.printing.command.MessageCommand;
import ch.fusun.baron.printing.service.impl.GameMessage;

/**
 * Shows all messages
 */
public class MessagesView extends ViewPart implements DataListener {

	@Inject
	private MessagingService messagingService;

	@Inject
	private ClientService client;

	@Inject
	private UserService userService;

	private StyledText text;
	private Text input;

	private List<GameMessage> messages = new LinkedList<GameMessage>();

	/**
	 * Injector constructor
	 */
	public MessagesView() {
	}

	@Override
	public void createPartControl(Composite parent) {
		parent.setLayout(new GridLayout());
		ReInjector.getInstance().reInject(this);
		messagingService.addDataListener(this);
		text = new StyledText(parent, SWT.BORDER);
		text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		text.setEditable(false);
		input = new Text(parent, SWT.BORDER);
		input.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		input.addTraverseListener(new TraverseListener() {
			@Override
			public void keyTraversed(TraverseEvent e) {
				client.execute(new MessageCommand(userService.getUser(), input
						.getText()));
				input.setText(""); //$NON-NLS-1$
			}
		});
	}

	@Override
	public void setFocus() {
		// Do nothing
	}

	private void handleDataChange() {
		messages = messages.subList(
				Math.min(10, Math.max(0, messages.size() - 10)),
				messages.size());
		messages.addAll(messagingService.getMessages());
		StringBuffer buffer = new StringBuffer();
		List<StyleRange> ranges = new LinkedList<StyleRange>();
		for (GameMessage message : messages) {
			String userString = message.getUser() == null ? "server" : message //$NON-NLS-1$
					.getUser().getName();

			userString += " (" + message.getTimeStamp() + ")"; //$NON-NLS-1$ //$NON-NLS-2$

			StyleRange userStyle = new StyleRange();
			userStyle.start = buffer.toString().length();
			userStyle.length = userString.length();
			userStyle.fontStyle = SWT.BOLD;
			userStyle.foreground = getSite()
					.getShell()
					.getDisplay()
					.getSystemColor(
							message.getUser() == null ? SWT.COLOR_RED
									: SWT.COLOR_BLUE);
			buffer.append(userString + ": " //$NON-NLS-1$
					+ message.getText() + "\n"); //$NON-NLS-1$
			ranges.add(userStyle);
		}
		text.setText(buffer.toString());
		for (StyleRange range : ranges) {
			text.setStyleRange(range);
		}
	}

	@Override
	public void dataChanged(DataUpdate update) {
		final Display display = getSite().getShell().getDisplay();
		display.asyncExec(new Runnable() {
			@Override
			public void run() {
				handleDataChange();
			}

		});
	}
}
